package lion.web.interceptors.ipac;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;

import lion.dev.lang.Init;
import lion.dev.lang.MapJ;
import lion.framework.core.anno.Initializer;
import lion.framework.core.conf.Config;
import lion.framework.core.conf.ConfigManager;
import lion.framework.core.util.StringLengthCompartor;

/**
 * IP Access Manager
 *
 * 对客户端ip访问进行控制
 *
 * <pre>
 * 	<framework>
 * 		<web>
 * 			<ipac>
 * 				<allow name="/*" ip="192.168.6,192.168.8" />
 * 				<deny name="/admin/*" ip="192.168.1.9"/>
 * 			</ipac>
 * 		</web>
 * 	</framework>
 * </pre>
 *
 * <pre>
 * time   2013年8月1日
 * mail   hl_0074@sina.com
 * </pre>
 *
 * @author lion.dev
 */
@Initializer
public class IPACManager implements Init {

	private static Map<String, IPAC> allows = new TreeMap<>(new StringLengthCompartor());
	private static Map<String, IPAC> denies = new TreeMap<>(new StringLengthCompartor());

	public static void addDenyIP(String path, String value) {

		if (StringUtils.isBlank(path) || StringUtils.isBlank(value)) { return; }

		denies.put(path, new IPAC(path, value));
	}

	public static void addAllowIP(String path, String ipPattern) {

		if (StringUtils.isBlank(path) || StringUtils.isBlank(ipPattern)) { return; }
		allows.put(path, new IPAC(path, ipPattern));
	}

	public static void clear() {

		allows.clear();
		denies.clear();
	}

	public static void removeDenyIP(String pattern) {

		denies.remove(pattern);
	}

	public static void removeAllowIP(String pattern) {

		allows.remove(pattern);
	}

	/**
	 * 全站路径访问控制
	 */
	public static boolean isIPAllowed(String ip) {

		return isIPAllowed(null, ip);
	}

	/**
	 * 某个特定路径访问控制
	 */
	public static boolean isIPAllowed(String path, String ip) {

		if (StringUtils.isBlank(path)) {
			path = "/";
		}

		boolean allow = true;

		if (!denies.isEmpty()) {
			for (IPAC ipac : denies.values()) {
				if (ipac.match(path)) {
					allow = !ipac.access(ip);
					break;
				}
			}
		}

		if (!allows.isEmpty()) {
			for (IPAC ipac : allows.values()) {
				if (ipac.match(path)) {
					allow = ipac.access(ip);
					break;
				}
			}
		}

		return allow;
	}

	@Override
	public void init() {

		Config config = ConfigManager.getConfig("framework");
		List<MapJ> allows = config.getList("framework.web.ipac.allow");
		List<MapJ> denys = config.getList("framework.web.ipac.deny");

		for (MapJ ips : allows) {

			String path = ips.getString("path");
			String value = ips.getString("ip");
			addAllowIP(path, value);
		}

		for (MapJ ips : denys) {
			String path = ips.getString("path");
			String value = ips.getString("ip");
			addDenyIP(path, value);
		}
	}

	@Override
	public int order() {

		return 0;
	}
}
